#!/usr/bin/env python3
"""
任务 2: 创建 Configuration 配置模型基础结构
文件: models/configuration.py
实现 Configuration 类的 __init__ 方法，接收根目录参数
添加 root_directory, include_patterns, exclude_patterns, verbose, dry_run 属性
实现 validate_config() 方法验证配置有效性
实现 get_default_config() 类方法提供默认配置
"""

import os
import pathlib
from typing import List, Optional, Dict, Any

class Configuration:
    """配置管理类"""
    
    def __init__(self, root_directory: str, 
                 include_patterns: Optional[List[str]] = None,
                 exclude_patterns: Optional[List[str]] = None,
                 verbose: bool = False,
                 dry_run: bool = False,
                 timeout: int = 300,
                 max_workers: int = 4):
        """
        初始化配置对象
        
        Args:
            root_directory: 根目录路径
            include_patterns: 包含的路径模式列表
            exclude_patterns: 排除的路径模式列表
            verbose: 是否启用详细输出
            dry_run: 是否为预览模式（不实际执行）
            timeout: 命令执行超时时间（秒）
            max_workers: 最大并发数
        """
        self.root_directory = root_directory
        self.include_patterns = include_patterns or []
        self.exclude_patterns = exclude_patterns or []
        self.verbose = verbose
        self.dry_run = dry_run
        self.timeout = timeout
        self.max_workers = max_workers
        
        # 验证配置
        self.is_valid = self.validate_config()
    
    def validate_config(self) -> bool:
        """
        验证配置有效性
        
        Returns:
            bool: 配置是否有效
        """
        try:
            # 验证根目录
            if not self.root_directory:
                self.error_message = "根目录不能为空"
                return False
            
            # 验证根目录路径
            root_path = pathlib.Path(self.root_directory)
            if not root_path.exists():
                self.error_message = f"根目录不存在: {self.root_directory}"
                return False
            
            if not root_path.is_dir():
                self.error_message = f"根目录不是有效的目录: {self.root_directory}"
                return False
            
            # 使用 realpath 防止路径遍历攻击
            real_path = os.path.realpath(self.root_directory)
            current_path = os.path.realpath(os.getcwd())
            if not real_path.startswith(current_path):
                self.error_message = f"根目录路径访问被拒绝: {self.root_directory}"
                return False
            
            # 验证超时时间
            if self.timeout <= 0:
                self.error_message = "超时时间必须大于 0"
                return False
            
            # 验证最大并发数
            if self.max_workers <= 0:
                self.error_message = "最大并发数必须大于 0"
                return False
            
            # 验证模式列表
            if not isinstance(self.include_patterns, list):
                self.error_message = "包含模式必须是列表"
                return False
            
            if not isinstance(self.exclude_patterns, list):
                self.error_message = "排除模式必须是列表"
                return False
            
            self.error_message = ""
            return True
            
        except Exception as e:
            self.error_message = f"配置验证失败: {str(e)}"
            return False
    
    def get_default_config(cls) -> 'Configuration':
        """
        获取默认配置
        
        Returns:
            Configuration: 默认配置对象
        """
        return cls(
            root_directory=".",
            include_patterns=[],
            exclude_patterns=["*/.git", "*/node_modules", "*/venv", "*/.venv"],
            verbose=False,
            dry_run=False,
            timeout=300,
            max_workers=4
        )
    
    def should_include_repository(self, repo_path: str) -> bool:
        """
        判断是否应该包含指定的仓库
        
        Args:
            repo_path: 仓库路径
            
        Returns:
            bool: 是否应该包含
        """
        import fnmatch
        
        # 如果没有包含模式，则包含所有仓库
        if not self.include_patterns:
            return True
        
        # 检查是否匹配包含模式
        for pattern in self.include_patterns:
            if fnmatch.fnmatch(repo_path, pattern):
                return True
        
        return False
    
    def should_exclude_repository(self, repo_path: str) -> bool:
        """
        判断是否应该排除指定的仓库
        
        Args:
            repo_path: 仓库路径
            
        Returns:
            bool: 是否应该排除
        """
        import fnmatch
        
        # 检查是否匹配排除模式
        for pattern in self.exclude_patterns:
            if fnmatch.fnmatch(repo_path, pattern):
                return True
        
        return False
    
    def get_summary(self) -> Dict[str, Any]:
        """
        获取配置摘要
        
        Returns:
            Dict[str, Any]: 配置摘要信息
        """
        return {
            "root_directory": self.root_directory,
            "include_patterns": self.include_patterns,
            "exclude_patterns": self.exclude_patterns,
            "verbose": self.verbose,
            "dry_run": self.dry_run,
            "timeout": self.timeout,
            "max_workers": self.max_workers,
            "is_valid": self.is_valid,
            "error_message": self.error_message
        }

def test_configuration():
    """测试 Configuration 类"""
    print("测试 Configuration 类...")
    
    # 测试默认配置
    default_config = Configuration.get_default_config()
    print(f"默认配置: {default_config.get_summary()}")
    
    # 测试自定义配置
    custom_config = Configuration(
        root_directory="/tmp",
        include_patterns=["*project*", "*repo*"],
        exclude_patterns=["*test*"],
        verbose=True,
        dry_run=True
    )
    print(f"自定义配置: {custom_config.get_summary()}")
    
    # 测试包含/排除逻辑
    test_path = "/tmp/my_project"
    print(f"路径 {test_path} 是否应该包含: {custom_config.should_include_repository(test_path)}")
    print(f"路径 {test_path} 是否应该排除: {custom_config.should_exclude_repository(test_path)}")
    
    # 测试无效配置
    invalid_config = Configuration("")
    print(f"无效配置: {invalid_config.get_summary()}")

if __name__ == "__main__":
    test_configuration()